module;
#include <array>
#include <iostream>

export module Code_23_1_1;

//[1]
template<typename T>
constexpr T sqrt1(T x)
{
    // handle cases where x and its square root are equal as a specialcase to simplify
    // the iteration criterion for larger x:
    if (x <= 1) 
    {
        return x;
    }
    // repeatedly determine in which half of a [lo, hi] interval the squareroot of x is located,
    // until the interval is reduced to just one value:
    T lo = 0, hi = x;
    for (;;) 
    {
        auto mid = (hi + lo) / 2, midSquared = mid * mid;
        if (lo + 1 >= hi || midSquared == x) 
        {
            // mid must be the square root:
            return mid;
        }
        //continue with the higher/lower half-interval:
        if (midSquared < x)
        {
            lo = mid;
        }
        else 
        {
            hi = mid;
        }
    }
}
export
namespace Code_23_1_1 {

    void run()
    {
        static_assert(sqrt1(25) == 5, ""); //OK (evaluated at compile time)
        static_assert(sqrt1(40) == 6, ""); //OK (evaluated at compile time)
        std::array<int, sqrt1(40) + 1> arr; //declares array of 7 elements (compile time)
        long long l = 53478;
        std::cout << sqrt1(l) << '\n';    //prints 231 (evaluated at run time)
    }
}

